home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac100% 1998 November
/
MAC100-1998-11.ISO.7z
/
MAC100-1998-11.ISO
/
オンラインソフト定点観測
/
ユーティリティ
/
Mops 3.2.sea
/
Mops 3.2
/
Mops ƒ
/
Args
next >
Wrap
Text File
|
1998-06-07
|
11KB
|
424 lines
¥ Support for named parms and local variables
cr .( loading Args...)
24 constant MAXPL ¥ Should be enough!!
false value LOCFLG ¥ true = looking for local var tokens
create PARMLIST maxPL cells reserve
0 value SVHASH
false value FLOAT?
0 value PLentry_addr
: INITLOCS ¥ Initializes flags etc.
0 -> #PL 0 -> #P 0 -> #F
0 -> FltFlg false -> locFlg ;
: FINDINPARMLIST ¥ ( addr -- loc# T OR -- F )
¥ loc# counts from right to left in the local/parm list.
dup 1+ c@ & % = -> float?
hash -> svHash false
#PL 0EXIT
ParmList #PL 4* bounds DO
svHash i @ =
IF ( found )
drop #PL
i parmlist - 4/
- 1- true LEAVE
THEN
4 +LOOP ;
: ADDTOPARMLIST ¥ ( addr -- ) Adds an element to ParmList.
¥ addr points to a counted string.
findinParmList ?error 95 ¥ Name not unique
#PL maxPL > ?error 110 ¥ too many parms/locals
FltFlg 1 << float? if 1 or 1 ++> #F then -> FltFlg
svHash
#PL 1 ++> #PL 4* ParmList + ! ;
: FIRSTCHR
here 1+ c@ ;
:f {
local? IF ¥ local? already non-zero - this ought to mean we're
¥ in a local section
local? 0< ?error 92 -1 -> local?
THEN
initLocs
BEGIN ¥ Loop to add parms/locals to parmlist
Mword drop
firstChr & - <> ¥ look for --
WHILE
firstChr dup & ¥ = swap & / = or
¥ Note: we allow / as an alternative to ¥ in this context,
¥ since it's an easy mistake to make, and / isn't a
¥ sensible parm name since it already has a meaning.
IF true -> locFlg
ELSE firstChr & } = ?error 111
locFlg nif 1 ++> #P then
here AddToParmList
THEN
REPEAT
local? NIF ¥ In local sections, we do this at :LOC
here -> PLentry_addr
¥ If we have temp objects, we'll have to backup the DP and
¥ recompile the entry sequence, since there'll be an extra local
¥ (the frame pointer)
PLentry
THEN
BEGIN ¥ Loop gobble chars until }
Mword drop
firstChr & } = ¥ look for }
UNTIL
¥ & } parse 2drop ¥ eat characters until }
¥ rest nip 0< ?error 112 ;f ¥ Err if no final }
;f
¥ FIND will call Pfind to attempt to find a name first.
¥ If Pfind finds the name is a local, it returns true and the
¥ cfa of LocParm, which is a dummy word whose handler compiles
¥ a local reference.
: PFIND ¥ ( str-addr -- cfa T | -- str-addr F )
state
NIF false
ELSE dup FindInParmList
IF ¥ Found
-> loc# drop
float? IF ['] FlocParm ELSE ['] locParm THEN
true
ELSE false ¥ Not found
THEN
THEN ;
: ,EXEC ¥ ( cfa n -- )
state
IF (compN) ELSE exN THEN ;
¥ Here are the different types that we can put prefixes on or send
¥ messages to:
TYPE{ notfnd locTyp flocTyp
tmpObjTyp objTyp ivarTyp classTyp superTyp
valTyp fvalTyp vecTyp dynVecTyp objptrTyp
regTyp lbTyp lbSelfTyp bktTyp wordTyp }
¥ notFnd - not previously defined
¥ locTyp - a local or named parm
¥ tmpObjTyp - a temporary (local) object
¥ objTyp - an object
¥ ivarTyp - an ivar
¥ classTyp - a class
¥ superTyp - a named superclass specified by msg: super> someClass
¥ valTyp - a value
¥ FvalTyp - a floating point value
¥ vecTyp - a vector
¥ dynVecTyp - a dynamic vector
¥ regTyp - a 680x0 register
¥ lbTyp - ** or [] meaning late bind
¥ lbSelfTyp - [self] meaning late bind to self
¥ BktTyp - [ - Neon-compatible late bind
¥ wordTyp - a word
¥ PRFTOKEN returns the type of a token for a prefix op.
¥ First we need to make some handler codes available above the Nucleus.
¥ In the PowerPC dic we're using $BCxx and $BDxx for non-colon handler
¥ codes to make disassembly easier, and as a sanity check for EXECUTE.
¥ We sort out the difference here. xx is positive, and half our 68k
¥ handler code (which is always even).
: HDLR ¥ ( cfa -- ha )
2- w@x
dup $ FE00 and $ BC00 =
IF $ FF and
dup $ 3D = IF drop 5 THEN ¥ treat vects and sVects the same
2* negate
THEN
;
' key hdlr constant VECTCODE
' base hdlr constant VALCODE
' ^base hdlr constant REGCODE
' hdlr hdlr constant WORDCODE
objPtr XX ' xx hdlr forget xx
constant OBJPTRCODE
dynamicVect XX ' xx hdlr forget xx
constant DYNVECTCODE
: PRFTOKEN ¥ ( -- cfa type )
' dup ['] locParm = IF locTyp EXIT THEN
dup ['] FlocParm = IF FlocTyp EXIT THEN
dup hdlr
CASE
valCode OF valTyp ENDOF
FvalCode OF FvalTyp ENDOF
vectCode OF vecTyp ENDOF
dynVectCode OF dynVecTyp ENDOF
regCode OF regTyp ENDOF
objPtrCode OF objPtrTyp ENDOF
114 die
ENDCASE ;
forward ToObjPtr ¥ Stores to an objPtr. Defined in file Class.
: ->
PrfToken ¥ All types are legal
objPtrTyp = IF toObjPtr EXIT THEN
$ 60 ( opcode for Store ) ,exec
; immediate ¥ NOTE: opcode for store hard coded here!!!
: CvrtFcode ¥ ( code -- code' )
CASE
$ 21 OF $ 41 ENDOF ¥ +
$ 22 OF $ 48 ENDOF ¥ -
$ 28 OF $ 55 ENDOF ¥ Neg
?error 114
ENDCASE ;
: (+->) ¥ ( code -- cfa code' )
PrfToken ( code cfa type ) rot swap ( cfa code type )
CASE
locTyp OF ENDOF
FlocTyp OF cvrtFcode ENDOF
valTyp OF ENDOF
FvalTyp OF cvrtFcode ENDOF
regTyp OF ENDOF
?error 114
ENDCASE ;
: (FOP)
PrfToken rot swap
CASE
locTyp OF ENDOF
FlocTyp OF ENDOF
FvalTyp OF ENDOF
?error 114
ENDCASE ;
¥ Note: the following opcodes have to agree with the definitions in
¥ OD.asm. I could have defined them as constants but this would have
¥ used up dictionary space for no great benefit.
: ++> $ 21 (+->) ,exec ; immediate
: +> postpone ++> ; immediate ¥ A synonym.
: --> $ 22 (+->) ,exec ; immediate
: AND> $ 23 (+->) ,exec ; immediate
: OR> $ 24 (+->) ,exec ; immediate
: XOR> $ 25 (+->) ,exec ; immediate
: NEG> $ 28 (+->) ,exec ; immediate
: NOT> $ 29 (+->) ,exec ; immediate
: *> $ 42 (fop) ,exec ; immediate
: /> $ 49 (fop) ,exec ; immediate
: ABS> $ 54 (fop) ,exec ; immediate
' Pfind -> Ufind
¥ =========== Local sections ===========
forward INITTEMPS
: ?LOC local? 0= ?error 91 ; ¥ "We're not in a local section"
: LOCAL
local? ?error 93 1 -> local? ¥ We change it to the normal -1
¥ as soon as "{" is read.
forward ;
: :LOC immediate
local? 1 = IF msg# 96 THEN ¥ warning - no locals defined
?loc 304
here ' (patch) (:) ¥ Like :F
#PL IF PLentry THEN
frameSize IF initTemps THEN
false -> local? ¥ We do this here so any EXITs
; ¥ tidy everything up properly
: ;LOC immediate
(;) 304 ?defn ; ¥ As local? is now false, everything else
¥ gets tidied up by (;)
¥ ============================================
false value compinline?
: EVALUATE { addr len ¥ x1 x2 x3 x4 -- ?? }
save-input drop ¥ Must be 4
-> x4 -> x3 -> x2 -> x1 ¥ Move input-stream specs to locals
addr -> src-start len -> src-len 0 >in ! -1 -> source-id
echo?
IF emb_obj_offs ." ***evaluating*** " addr len type cr
-> emb_obj_offs
THEN
interpret
x1 x2 x3 x4 4 restore-input ?error 25 ;
¥ We can EVALUATE strings which might have embedded returns, and we can't
¥ just convert returns to blanks since we want the comment operator ¥
¥ to only skip to the end of the line, not the end of the string. We handle
¥ this by defining an immediate "word" which just consists of a return, which
¥ does nothing. We initially define it as X then patch it. Our dic
¥ threading scheme doesn't clobber this since we just hash on the length,
¥ which remains 1.
: X ; immediate
13 ( cr ) ' x >name 1+ c!
: (COMPINL) ¥ ( cfa -- )
true -> compinline?
2+ count evaluate
false -> compinline? ;
' (compinl) -> compinline
(*
: INLINE{ immediate
method? IF -4 allot THEN ¥ Wipe out method entry sequence
¥ %%% watch this on PPC!
inlMk w, & } ,str
align-dp
method? IF Mentry THEN ¥ Recompile method entry sequence
postpone ] ;
*)
: INLINE{ { ¥ addr len sv>in --< inline source text> }
method? IF -4 allot THEN ¥ Wipe out method entry sequence
¥ %%% watch this on PPC!
inlMk w,
DP >r ¥ save location of start of string
¥ for EVALUATE below
& } ,str
align-dp
method? IF Mentry THEN ¥ recompile method entry sequence
r> count evaluate ¥ compile out-of-line code
¥ Previous Mops versions required the out-of-line code to be
¥ explicitly put in. We don't need this any more, but we
¥ still need to skip it if it's there.
BEGIN
>in @ -> sv>in
Mword count -> len -> addr
addr len " ;" s=
addr len " ;M" s= or
UNTIL
sv>in >in !
; immediate
: [IF] { flag ¥ addr len level done? -- }
flag ?EXIT
false -> done? 1 -> level
BEGIN
Mword count -> len -> addr
addr len " [THEN]" s= IF 1 --> level
ELSE addr len " [ELSE]" s= IF level 1 =
IF true -> done? THEN
ELSE addr len " [IF]" s= IF 1 ++> level
THEN THEN THEN
level NIF true -> done? THEN
done?
UNTIL
; immediate
: [ELSE] { ¥ addr len level done? -- }
false -> done? 1 -> level
BEGIN
Mword count -> len -> addr
addr len " [THEN]" s= IF 1 --> level
ELSE addr len " [IF]" s= IF 1 ++> level
THEN THEN
level NIF true -> done? THEN
done?
UNTIL
; immediate
: [THEN] ; immediate
¥ =============================
¥ ASSERTIONS
¥ =============================
(* Assertions allow you, during development, to ensure that
things are the way they're supposed to be at key places.
Usage:
ASSERT{ <something that evaluates to a flag> }
If ASSERTIONS? is true, this will give error 216 ("assertion failed")
if the evaluated flag is false. If ASSERTIONS? is false, nothing
will happen - the code between ASSERT{ and } isn't executed.
ASSERTIONS? can be defined and redefined however and whenever you
like, as long as it returns a flag - ASSERT{ tests it via EVALUATE,
so the latest definition will be the one that gets looked at.
If you have ASSERTIONS? defined as a constant with value false, no
code will even be compiled for the assertion test - you can use this
for code that you know works.
*)
false constant assertions? ¥ redefine however and whenever necessary
: }ASSERT
134 ?pairs
['] } >body !
" NIF 216 die THEN THEN" evaluate ¥ assertion failed!
; immediate
: ASSERT{
?comp
" assertions? if" evaluate
['] } >body @ ¥ save old action for "}"
['] }assert -> } ¥ "}" will now be same as }assert
134
; immediate
¥ ==============================
¥ SUNDRY INLINES
¥ ==============================
: UNDER+ ( n1 n2 n3 -- n1+n3 n2 )
inline{ rot + swap} ;
load class